#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>

#ifdef TEXT_MODE
#include "card_img.h"
#endif

#include "base_card.h"
#include "board.h"

#include "dqueue.h"
#include "my_card_dqueue.h"
#include "account.h"
#include "mempool.h"


void test_dqueue()
{
	int size;
	Dqueue *dq, *dq_temp;
	dq = (Dqueue *)card_shuffle();
	size = dq->size;
	dq_temp = dq;
	printf("==== DQUEUE INFO ====\n");
	printf("1. maxSize = %d\n", dq->maxSize);
	printf("2. size =%d\n", dq->size);
	printf("3. head =%d\n", dq->head);
	printf("4. tail =%d\n", dq->tail);
	printf("=====================\n");
	
	while(!isEmptyDqueue(dq))
	{
		int *data = delHeadDqueue(dq);
		printf("%d ",*data);
	}
	printf("\n");

	free_shuffle_card_order(dq);
}
/*
 * 	The rotate_enum
 *
	ROTATE_RIGHT_270 = -3,
	ROTATE_RIGHT_180,
	ROTATE_RIGHT_90,
	ROTATE_NONE,
	ROTATE_LEFT_90,
	ROTATE_LEFT_180,
	ROTATE_LEFT_270,
*/
void test_rotate(int idx, int rotate_enum)
{
	struct card *temp;
	temp = get_card(idx);
	printf("==================================\n");
	printf("Before rotate ttype:(%d,%d,%d,%d)\n",
		temp->terrain_type[0],
		temp->terrain_type[1],
		temp->terrain_type[2],
		temp->terrain_type[3]);
	//print_card_pixels(idx);
	show_card_image(idx);
	//card_rotate(idx, ROTATE_RIGHT_90);
	card_rotate(idx, rotate_enum);
	printf("After rotate ttype(%d,%d,%d,%d)\n",
		terrain_type(idx, TOP),
		terrain_type(idx, RIGHT),
		terrain_type(idx, BOTTOM),
		terrain_type(idx, LEFT));
	printf("==================================\n");
	//print_card_pixels(idx);
	show_card_image(idx);
}
// Just a test function
void test_function()
{
	// test rotate
	test_rotate(INIT_CARD_INDEX, ROTATE_RIGHT_90);
	test_rotate(INIT_CARD_INDEX, ROTATE_RIGHT_90);
	test_rotate(INIT_CARD_INDEX, ROTATE_RIGHT_90);
	// test rotate again..
	test_rotate(15, ROTATE_LEFT_90);
	test_rotate(15, ROTATE_LEFT_90);
	test_rotate(15, ROTATE_LEFT_90);

	// Assign some cards into board
	set_board_card(INIT_CARD_INDEX, 72, 72);
	set_board_card(1, 70, 75);
	set_board_card(2, 74, 74);
}
// Check if source_id can insert into target_id    >//////<
// Then return the flag 1111 or 0010
// 			NRSW    NRSW
// 	Example:
// 		card 15 want to insert into card 54(init card),
// 		will return 1111
int get_insertable_flag(int target_id, int source_id)
{
	int flag = 0;
	if(is_top_ok(target_id, source_id))
		flag+= 8;
	if(is_right_ok(target_id, source_id))
		flag+= 4;
	if(is_bottom_ok(target_id, source_id))
		flag+= 2;
	if(is_left_ok(target_id, source_id))
		flag+= 1;
	return flag;
}
int insertable(int target_id, int source_id)
{
	int flag; // insertable_flag (0~F)
	int i;
	int ret =0;
	for(i=0;i<4;i++) // Max rotate number is 4, rotate a circle
	{
		flag = get_insertable_flag( target_id, source_id);
		//printf("(%d):%2d ", i, flag);
		ret+=(flag<<4*i);
		card_rotate(source_id, ROTATE_RIGHT_90);
	}
	// ret flag
	// Ex:	card 1 want to insert near card 2
	// 		ret = 0x00005FA0
	// 0: Without rotate, can not insert
	// A: Right rotate  90, top, bottom are possible
	// F: Right rotate 180, all connection are possible
	// 5: Right rotate 270, left, right are possible
	
#if 0
	printf("ret = 0x%08X\n", ret);
	printf("xxx = (%2d, %2d , %2d, %2d)\n", 
		TOP_FLAG(ret),
		RIGHT_FLAG(ret),
		BOTTOM_FLAG(ret),
		LEFT_FLAG(ret));
#endif
	return ret;
}
void test_insert()
{
	int i;
	int target_id = 0;
	// check card 1 ~ 71
	for(i=0;i<TOTAL_CARD;i++)
	{
		if(i == target_id)
			continue;
		printf("(%d):", i);
		insertable(target_id, i);
	}
}
// scan boundary to find a place, and put it into board.
void scan_put_card(int card_idx)
{
	int x0, y0, x1, y1;
	int i,j;
	int target;
	int flag;
	x0 = get_board_left()-1;
	y0 = get_board_top()-1;
	x1 = get_board_right()+1;
	y1 = get_board_bottom()+1;
	
	if(x0 < 0)
		x0 = 0;
	if(y0 < 0)
		y0 = 0;
	if(x1 > 143)
		x1 = 143;
	if(y1 > 143)
		y1 = 143;

	printf("(%2d) scan (%d,%d) to %d,%d)\n", card_idx, x0, y0, x1, y1);

	// Make sure that auto_rotate() must called before set_board_card()
	for(i=y0; i<y1; i++)
	{
		for(j=x0;j<x1;j++)
		{
			if(board_occupy(j, i) == BOARD_NOT_OCCUPY)
			{
				// top have card
				target = board_occupy(j, i-1);
				if(IS_OCCUPY(target))
				{
					flag = BOTTOM_FLAG(insertable(target, card_idx));
					if(flag)
					{
						printf("Bottom flag = 0x%08X\n", flag);
						auto_rotate(card_idx, flag, BOTTOM);
						set_board_card(card_idx, j, i);
						return;
					}
				}
				// right have card
				target = board_occupy(j+1, i);
				if(IS_OCCUPY(target))
				{
					flag = LEFT_FLAG(insertable(target, card_idx));
					if(flag)
					{
						printf("Left flag = 0x%08X\n", flag);
						auto_rotate(card_idx, flag, LEFT);
						set_board_card(card_idx, j, i);
						return;
					}
				}
				// bottom have card
				target = board_occupy(j, i+1);
				if(IS_OCCUPY(target))
				{
					flag = TOP_FLAG(insertable(target, card_idx));
					if(flag)
					{
						printf("Top flag = 0x%08X\n", flag);
						auto_rotate(card_idx, flag, TOP);
						set_board_card(card_idx, j, i);
						return;
					}
				}
				// left have card
				target = board_occupy(j-1, i);
				if(IS_OCCUPY(target))
				{
					flag = RIGHT_FLAG(insertable(target, card_idx));
					if(flag)
					{
						printf("Right flag = 0x%08X\n", flag);
						auto_rotate(card_idx, flag, RIGHT);
						set_board_card(card_idx, j, i);
						return;
					}
				}
			}
		}
	}
}
void random_assign_board()
{
	int i;
	int curr_x = 72;
	int curr_y = 72;
	int card_idx;
	Dqueue *dq;
	dq = card_shuffle();
	
	init_board();
	// First, put init card into middle of board.
	set_board_card(INIT_CARD_INDEX, curr_x, curr_y);
	
	//for(i=0;i<3;i++)
	for(i=0;i<TOTAL_CARD;i++)
	{
		// Get card id
		card_idx = *(int *)(delHeadDqueue(dq));
		if(card_idx == INIT_CARD_INDEX)
			continue;
		// find a place to put.
		scan_put_card(card_idx);
	}
	printf("\n");
	
	free_shuffle_card_order(dq);
}
int main(int argc, char *argv[])
{
	int list[28] = {512,512,512,512,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4};
	createMempoolSet(4,28,list,1); // 0 is used for "main thread"
	
	//srand(time(NULL));
	//random_assign_board();

	//printf("------------------\n");
	//print_board_pixels();
	//show_board();
	//print_board();

	//test_dqueue();	
	//test_insert();
	AH_create_account("testtest", "1234567890");
	AH_create_account("testtest", "1234567890");
	AH_create_account("test", "1234567");
	AH_create_account("abc", "1234567");
	AH_create_account("abcd", "1234567");
	AH_create_account("abcde", "1234567");
	AH_create_account("abcdef", "1234567");
	AH_create_account("abcdefg", "1234567");
	AH_create_account("abcdefgh", "1234567");
	AH_create_account("abcdefghi", "1234567");
	
	// finalize the mempool
	FILE *fp_mem = fopen("mempool.log","w");
	usageMempoolSet(fp_mem);
	fclose(fp_mem);
	freeMempoolSet();
	return 0;
}
